const express = require('express');
const http = require('http');
const https = require('https');
const socketIo = require('socket.io');
const path = require('path');
const fs = require('fs');


const app = express();

const options = {
    key: fs.readFileSync('ssl/key.pem'),
    cert: fs.readFileSync('ssl/cert.pem')
};
// server = https.createServer(options, app);

server = http.createServer(app);

// 创建Socket.IO服务器
io = socketIo(server, {
    cors: {
        origin: "*",
        methods: ["GET", "POST"]
    }
});

// 提供静态文件
app.use(express.static(path.join(__dirname, 'public')));

// 健康检查端点
app.get('/health', (req, res) => {
    res.status(200).json({
        status: 'ok',
        timestamp: new Date().toISOString(),
        uptime: process.uptime(),
        memory: process.memoryUsage(),
        rooms: Object.keys(rooms).length,
        connections: connectionStats.currentConnections
    });
});

// 获取服务器信息端点
app.get('/api/info', (req, res) => {
    res.json({
        totalRooms: Object.keys(rooms).length,
        totalUsers: Object.values(rooms).flat().length,
        serverTime: new Date().toISOString(),
        connectionStats: connectionStats
    });
});

// 获取房间列表端点
app.get('/api/rooms', (req, res) => {
    const roomsInfo = Object.keys(rooms).map(roomId => ({
        roomId: roomId,
        userCount: rooms[roomId].length,
        users: rooms[roomId].map(userId => userId.substring(0, 8))
    }));
    res.json(roomsInfo);
});

// 存储房间信息
const rooms = {};

// 记录连接统计
let connectionStats = {
    totalConnections: 0,
    currentConnections: 0,
    peakConnections: 0,
    startTime: new Date().toISOString()
};

io.on('connection', (socket) => {
    connectionStats.totalConnections++;
    connectionStats.currentConnections++;
    connectionStats.peakConnections = Math.max(
        connectionStats.peakConnections,
        connectionStats.currentConnections
    );

    console.log(`[${new Date().toISOString()}] 用户连接: ${socket.id} (当前在线: ${connectionStats.currentConnections})`);

    // 发送连接统计
    socket.emit('connection-stats', connectionStats);

    // 加入房间
    socket.on('join-room', (roomId) => {
        if (!roomId || typeof roomId !== 'string') {
            socket.emit('error', {message: '无效的房间ID'});
            return;
        }

        // 限制房间ID长度
        if (roomId.length > 50) {
            socket.emit('error', {message: '房间ID过长'});
            return;
        }

        socket.join(roomId);

        if (!rooms[roomId]) {
            rooms[roomId] = [];
        }

        // 检查用户是否已在房间中
        if (!rooms[roomId].includes(socket.id)) {
            rooms[roomId].push(socket.id);
        }

        console.log(`[${new Date().toISOString()}] 用户 ${socket.id} 加入房间 ${roomId} (房间人数: ${rooms[roomId].length})`);

        // 通知房间内其他用户有新用户加入
        socket.to(roomId).emit('user-joined', socket.id);

        // 如果房间里已经有其他用户，发送现有用户列表
        const otherUsers = rooms[roomId].filter(id => id !== socket.id);
        if (otherUsers.length > 0) {
            socket.emit('existing-users', otherUsers);
        }

        // 发送房间信息
        const roomInfo = {
            roomId: roomId,
            userCount: rooms[roomId].length,
            users: rooms[roomId]
        };

        socket.emit('room-info', roomInfo);

        // 向房间内所有用户广播房间信息更新
        io.to(roomId).emit('room-info', roomInfo);
    });

    // 转发WebRTC信令消息
    socket.on('offer', (data) => {
        if (!data.target || !data.sdp) {
            socket.emit('error', {message: '无效的offer数据'});
            return;
        }

        // 验证目标用户是否存在
        const targetSocket = io.sockets.sockets.get(data.target);
        if (!targetSocket) {
            socket.emit('error', {message: '目标用户不存在'});
            return;
        }

        socket.to(data.target).emit('offer', {
            sdp: data.sdp,
            sender: socket.id
        });
        console.log(`[${new Date().toISOString()}] 转发offer: ${socket.id} -> ${data.target}`);
    });

    socket.on('answer', (data) => {
        if (!data.target || !data.sdp) {
            socket.emit('error', {message: '无效的answer数据'});
            return;
        }

        // 验证目标用户是否存在
        const targetSocket = io.sockets.sockets.get(data.target);
        if (!targetSocket) {
            socket.emit('error', {message: '目标用户不存在'});
            return;
        }

        socket.to(data.target).emit('answer', {
            sdp: data.sdp,
            sender: socket.id
        });
        console.log(`[${new Date().toISOString()}] 转发answer: ${socket.id} -> ${data.target}`);
    });

    socket.on('ice-candidate', (data) => {
        if (!data.target || !data.candidate) {
            socket.emit('error', {message: '无效的ICE候选数据'});
            return;
        }

        // 验证目标用户是否存在
        const targetSocket = io.sockets.sockets.get(data.target);
        if (!targetSocket) {
            return; // ICE候选可能在连接建立过程中失败，不需要报错
        }

        socket.to(data.target).emit('ice-candidate', {
            candidate: data.candidate,
            sender: socket.id
        });
    });

    // 用户主动离开房间
    socket.on('leave-room', (roomId) => {
        leaveRoom(socket, roomId, true);
    });

    // 获取房间信息
    socket.on('get-room-info', (roomId) => {
        if (rooms[roomId]) {
            socket.emit('room-info', {
                roomId: roomId,
                userCount: rooms[roomId].length,
                users: rooms[roomId]
            });
        } else {
            socket.emit('room-info', {
                roomId: roomId,
                userCount: 0,
                users: []
            });
        }
    });

    // 心跳检测
    socket.on('ping', () => {
        socket.emit('pong');
    });

    // 用户断开连接
    socket.on('disconnect', (reason) => {
        connectionStats.currentConnections--;
        console.log(`[${new Date().toISOString()}] 用户断开连接: ${socket.id}, 原因: ${reason} (当前在线: ${connectionStats.currentConnections})`);

        // 从所有房间中移除用户
        Object.keys(rooms).forEach(roomId => {
            leaveRoom(socket, roomId, false);
        });
    });

    // 错误处理
    socket.on('error', (error) => {
        console.error(`[${new Date().toISOString()}] Socket错误 (${socket.id}):`, error);
        socket.emit('error', {message: '服务器内部错误'});
    });
});

// 离开房间的公共函数
function leaveRoom(socket, roomId, notifyClient = true) {
    if (!rooms[roomId]) return;

    const index = rooms[roomId].indexOf(socket.id);
    if (index !== -1) {
        rooms[roomId].splice(index, 1);
        socket.leave(roomId);

        console.log(`[${new Date().toISOString()}] 用户 ${socket.id} 离开房间 ${roomId} (剩余人数: ${rooms[roomId].length})`);

        // 通知房间内其他用户
        socket.to(roomId).emit('user-left', socket.id);

        // 向房间内剩余用户发送更新的房间信息
        if (rooms[roomId].length > 0) {
            const roomInfo = {
                roomId: roomId,
                userCount: rooms[roomId].length,
                users: rooms[roomId]
            };
            io.to(roomId).emit('room-info', roomInfo);
        }

        // 如果房间为空，删除房间
        if (rooms[roomId].length === 0) {
            delete rooms[roomId];
            console.log(`[${new Date().toISOString()}] 房间 ${roomId} 已删除（无用户）`);
        }

        if (notifyClient) {
            socket.emit('left-room', roomId);
        }
    }
}

// 定期清理和统计
setInterval(() => {
    // 清理空房间
    const emptyRooms = Object.keys(rooms).filter(roomId => rooms[roomId].length === 0);
    emptyRooms.forEach(roomId => {
        delete rooms[roomId];
    });

    // 打印统计信息
    const stats = {
        timestamp: new Date().toISOString(),
        rooms: Object.keys(rooms).length,
        onlineUsers: connectionStats.currentConnections,
        totalConnections: connectionStats.totalConnections,
        peakConnections: connectionStats.peakConnections,
        uptime: Math.floor(process.uptime()),
        memory: Math.floor(process.memoryUsage().rss / 1024 / 1024) + 'MB'
    };

    console.log(`[统计] ${JSON.stringify(stats)}`);

    // 向所有客户端广播服务器状态
    io.emit('server-stats', stats);

}, 300000); // 每5分钟执行一次

// 每分钟的轻量级清理
setInterval(() => {
    // 清理断开连接但仍在房间中的用户
    Object.keys(rooms).forEach(roomId => {
        const validUsers = rooms[roomId].filter(userId => {
            return io.sockets.sockets.has(userId);
        });

        if (validUsers.length !== rooms[roomId].length) {
            rooms[roomId] = validUsers;
            if (validUsers.length === 0) {
                delete rooms[roomId];
                console.log(`[清理] 删除空房间: ${roomId}`);
            } else {
                console.log(`[清理] 房间 ${roomId} 清理了 ${rooms[roomId].length - validUsers.length} 个无效用户`);
                // 通知房间内剩余用户更新信息
                io.to(roomId).emit('room-info', {
                    roomId: roomId,
                    userCount: validUsers.length,
                    users: validUsers
                });
            }
        }
    });
}, 60000); // 每分钟执行一次

// 优雅关闭处理
function gracefulShutdown(signal) {
    console.log(`[${new Date().toISOString()}] 收到${signal}信号，正在关闭服务器...`);

    // 通知所有客户端服务器即将关闭
    io.emit('server-shutdown', {
        message: '服务器维护中，请稍后重新连接',
        timestamp: new Date().toISOString()
    });

    // 等待通知发送完成
    setTimeout(() => {
        // 关闭所有socket连接
        io.close(() => {
            console.log('所有Socket连接已关闭');

            // 关闭HTTP服务器
            server.close(() => {
                console.log('HTTP服务器已关闭');

                // 打印最终统计信息
                console.log(`[最终统计] 总连接数: ${connectionStats.totalConnections}, 峰值连接数: ${connectionStats.peakConnections}`);
                console.log(`[最终统计] 运行时间: ${Math.floor(process.uptime())}秒`);

                process.exit(0);
            });
        });
    }, 1000); // 等待1秒让通知发送完成

    // 强制退出保险
    setTimeout(() => {
        console.log('强制退出');
        process.exit(1);
    }, 10000); // 10秒后强制退出
}

// 信号处理
process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
process.on('SIGINT', () => gracefulShutdown('SIGINT'));

// 未捕获的异常处理
process.on('uncaughtException', (error) => {
    console.error(`[${new Date().toISOString()}] 未捕获的异常:`, error);
    gracefulShutdown('UNCAUGHT_EXCEPTION');
});

process.on('unhandledRejection', (reason, promise) => {
    console.error(`[${new Date().toISOString()}] 未处理的Promise拒绝:`, reason);
    gracefulShutdown('UNHANDLED_REJECTION');
});

// 启动服务器
server.listen(443, () => {
    const serverInfo = {
        name: 'WebRTC语音通话服务器',
        nodeVersion: process.version,
        pid: process.pid,
        environment: process.env.NODE_ENV || 'development',
        startTime: new Date().toISOString()
    };

    console.log('========================================');
    console.log('🎙️  WebRTC语音通话服务器已启动');
    console.log('========================================');
    console.log(`🕐 启动时间: ${serverInfo.startTime}`);
    console.log(`🔧 Node.js版本: ${serverInfo.nodeVersion}`);
    console.log(`🆔 进程ID: ${serverInfo.pid}`);
    console.log(`🌍 环境: ${serverInfo.environment}`);
    console.log('========================================');

    // 保存服务器信息供健康检查使用
    global.serverInfo = serverInfo;
}).on('error', (error) => {
    console.error(`[${new Date().toISOString()}] 服务器启动失败:`, error);
    process.exit(1);
});
